<?php

namespace App\Trip\Wechat\Account;

use App\Jobs\User\ProcessUserAvatar;
use App\Models\User\Repositories\Interfaces\UserRepositoryInterface;
use App\Models\User\Repositories\Interfaces\WechatMiniAppUserRepositoryInterface;
use App\Models\User\User;
use App\Trip\Wechat\AppId;
use App\Trip\Wechat\MiniApp\Application;
use App\Trip\Wechat\MiniApp\WechatMiniApp;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class WechatMiniAppLogin implements WechatLoginInterface
{

    protected Application $miniapp;
    protected array       $data;
    protected             $userRepo;
    protected             $appUserRepo;

    public function __construct(array $data = [])
    {
        $this->data        = $data;
        $this->userRepo    = app(UserRepositoryInterface::class);
        $this->appUserRepo = app(WechatMiniAppUserRepositoryInterface::class);
        $config            = [];
        $config['appid']   = AppId::getAppId();
        $this->miniapp     = (new WechatMiniApp($config))->getApplication();
    }

    public function application(): Application
    {
        return $this->miniapp;
    }

    /**
     * @throws Exception
     */
    public function login(): WechatLoginResp
    {
        $userData    = $this->decryptData();
        $user        = $this->userRepo->getUserByUnionIdOpenIdType($userData['unionid'], $userData['openid'], User::CLIENT_TYPE_WECHAT_MINIAPP);
        $addUserData = [
            'openid'      => $userData['openid'],
            'unionid'     => $userData['unionid'],
            'avatar'      => $userData['avatarUrl'],
            'nickname'    => $userData['nickName'],
            'appid'       => $this->miniapp->getAppId(),
            'client_type' => User::CLIENT_TYPE_WECHAT_MINIAPP,
        ];

        if (!$user) {
            $user = $this->userRepo->addUser($addUserData);
            ProcessUserAvatar::dispatch($user);
        } else {
            $mini_user = $this->userRepo->getMiniAppUserByOpenId($user, $addUserData['openid']);
            if (!$mini_user) {
                $this->userRepo->addMiniUser($user, $addUserData);
            }
            $u_data = [

            ];
            if ($user->getNickName() != $userData['nickName']) {
                $u_data['nickname'] = $addUserData['nickname'];
            }
            $ac = "User:{$user->getUnionId()}:Avatar";
            if (!Cache::has($ac)) {
                $u_data['avatar'] = $addUserData['avatar'];
                ProcessUserAvatar::dispatch($user);
            }

            $u_data && $this->userRepo->updateUser($user, $u_data);
        }
        return new WechatLoginResp($user);
    }

    /**
     * @throws Exception
     */
    protected function decryptData(): array
    {
        extract($this->data);
        try {
            $userData = $this->miniapp->getUserData($code, $iv, $encryptedData);
        } catch (Exception $exception) {
            Log::error('用户信息获取失败'.$exception->getMessage());
            throw new Exception('用户信息获取失败', 400);
        }
        return $userData;
    }
}